package com.feasy.generator.generatorcode.utils;

import com.feasy.generator.generatorcode.domain.Column;
import com.feasy.generator.generatorcode.domain.Table;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 代码生成器   工具类
 */
public class GeneratorUtils {


    public static List<String> getTemplates() {
        List<String> templates = new ArrayList<String>();

        templates.add("/templates/generator/action/DeleteAction.java.vm");
        templates.add("/templates/generator/action/SaveAction.java.vm");
        templates.add("/templates/generator/action/ShowAction.java.vm");
        templates.add("/templates/generator/dao/DAO.java.vm");
        templates.add("/templates/generator/dao/hibernateImpl/DAOImpl.java.vm");
        templates.add("/templates/generator/domain/Domain.java.vm");
        templates.add("/templates/generator/page/form.jsp.vm");
        templates.add("/templates/generator/page/list.jsp.vm");
        templates.add("/templates/generator/page/view.jsp.vm");
        templates.add("/templates/generator/service/Service.java.vm");
        templates.add("/templates/generator/service/ServiceImpl.java.vm");
        return templates;
    }

    /**
     * 生成代码
     * @throws Exception
     */
    public static void generatorCode(String tableName, String tableComment, List<Map<String, Object>> columns,String intercode,
                                     ZipOutputStream zip, String packagePath, String author, String email) {

        //表信息
        Table tableDO = new Table();

        tableDO.setTableName(tableName);
        tableDO.setComments(tableComment);
        //表名转换成Java类名
        String className = tableToJava(tableDO.getTableName());
        tableDO.setClassName(className);
        tableDO.setClassname(StringUtils.uncapitalize(className));
        if(StringUtils.isNotEmpty(intercode)&&intercode.equals("1")) {
        	tableDO.setAppInterface("1");
        }else {
        	tableDO.setAppInterface("0");
        }
        String constructorParams = "";
        String sqlcode = "select ";
        //列信息
        List<Column> columsList = new ArrayList();
        for (Map<String, Object> column : columns) {
            Column columnDO = new Column();
            String columnName = column.get("columnName").toString();
            columnDO.setColumnName(columnName);
            columnDO.setDataType(column.get("dataType").toString());
            if(column.get("columnComment")!=null) {
	            columnDO.setComments(column.get("columnComment").toString());
	            }else {
	            	columnDO.setComments("");
            }
            if(column.get("extra")!=null)
            columnDO.setExtra(column.get("extra").toString());//'auto_increment'
            //列名转换成Java属性名
            String attrName = columnToJava(columnName);
            columnDO.setAttrName(attrName);
            String attrname = StringUtils.uncapitalize(attrName);
            columnDO.setAttrname(attrname);
            columnDO.setAttrnametolower(attrname.toLowerCase());
            //列的数据类型，转换成Java类型
            String attrType  =  PropertiesUstils.getString("generator.properties", columnDO.getDataType());

            attrType = attrType==""?"unknowType":attrType;
            columnDO.setAttrType(attrType);
            constructorParams += attrType+" "+attrname+",";

            //是否主键
            if (column.get("columnKey")!=null&&"PRI".equalsIgnoreCase(column.get("columnKey").toString()) && tableDO.getPk() == null) {
                tableDO.setPk(columnDO);
            }
            else
            {
                columsList.add(columnDO);
            }
            sqlcode = sqlcode + column.get("columnName").toString()+" as  "+StringUtils.uncapitalize(attrName)+" ,";
        }
        if(constructorParams.endsWith(",")){
            constructorParams = constructorParams.substring(0,constructorParams.length()-2);
        }
        tableDO.setConstructorParams(constructorParams);
        if(sqlcode.endsWith(",")){
        	sqlcode = sqlcode.substring(0,sqlcode.length()-2);
        }
        sqlcode = sqlcode + " from  " +tableName;
        tableDO.setSqlcode(sqlcode);
        //没主键，则第一个字段为主键
        if (tableDO.getPk() == null) {
            tableDO.setPk(columsList.get(0));
            columsList.remove(0);
        }
        tableDO.setColumns(columsList);

        //设置velocity资源加载器
        Properties prop = new Properties();
        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        Velocity.init(prop);
        String packagestr = packagePath;
        //封装模板数据
        Map<String, Object> map = new HashMap(16);
        map.put("tableName", tableDO.getTableName());
        map.put("comments", tableDO.getComments());
        map.put("pk", tableDO.getPk());
        map.put("pk-tolower", tableDO.getPk().getAttrname().toLowerCase());
        map.put("className", tableDO.getClassName());
        map.put("classname", tableDO.getClassname());
        map.put("pathName", packagestr);
        map.put("columns", tableDO.getColumns());
        map.put("package",  packagestr);
        map.put("author", author);
        map.put("email", email);
        map.put("datetime", DateUtils.getDateTime());
        map.put("constructorParams", tableDO.getConstructorParams());
        map.put("appinterfacecode", tableDO.getAppInterface());
        map.put("sqlcode", tableDO.getSqlcode());
        VelocityContext context = new VelocityContext(map);
        System.out.println("---------"+tableDO.getAppInterface()+"---------------");
        //获取模板列表
        List<String> templates = getTemplates();
        for (String template : templates) {
            try {
                //渲染模板
                StringWriter sw = new StringWriter();
                Template tpl = Velocity.getTemplate(template, "UTF-8");
                tpl.merge(context, sw);
                //添加到zip
                zip.putNextEntry(new ZipEntry(getFileName(template, tableDO.getClassname(), tableDO.getClassName(), packagestr)));
                IOUtils.write(sw.toString(), zip, "UTF-8");
                IOUtils.closeQuietly(sw);
                zip.closeEntry();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 列名转换成Java属性名
     */
    public static String columnToJava(String columnName) {
        return WordUtils.capitalizeFully(columnName, new char[]{'_'}).replace("_", "");
    }
    /**
     * 表名转换成Java类名
     */
    public static String tableToJava(String tableName) {
//            tableName = tableName.substring(tableName.indexOf("_") + 1);
        return columnToJava(tableName);
    }
    /**
     * 获取文件名
     */
    public static String getFileName(String template, String classname, String className, String packageName) {
        String packagePath = "main" + File.separator + "java" + File.separator;
        if (StringUtils.isNotBlank(packageName)) {
            packagePath += packageName.replace(".", File.separator) + File.separator;
        }

        if (template.contains("Domain.java.vm")) {
            return packagePath + classname +File.separator+ "domain" + File.separator + className + ".java";
        }

        if (template.contains("DAO.java.vm")) {
            return packagePath +classname +File.separator+ "dao" + File.separator + className + "DAO.java";
        }

        if (template.contains("DAOImpl.java.vm")) {
            return packagePath +classname +File.separator+ "dao" + File.separator+"hibernateImpl"+File.separator + className + "DAOImpl.java";
        }

        if (template.contains("Service.java.vm")) {
            return packagePath +classname +File.separator+ "service" + File.separator + className + "Service.java";
        }

        if (template.contains("ServiceImpl.java.vm")) {
            return packagePath +classname +File.separator+ "service" + File.separator + className + "ServiceImpl.java";
        }

        if (template.contains("SaveAction.java.vm")) {
            return packagePath +classname +File.separator+ "action" + File.separator + className + "SaveAction.java";
        }

        if (template.contains("ShowAction.java.vm")) {
            return packagePath +classname +File.separator+ "action" + File.separator + className + "ShowAction.java";
        }
        if (template.contains("DeleteAction.java.vm")) {
            return packagePath +classname +File.separator+ "action" + File.separator + className + "DeleteAction.java";
        }
        if (template.contains("list.jsp.vm")) {
            return "main" + File.separator + "pages" + File.separator  + className.toLowerCase() + File.separator +  className.toLowerCase()+"list.jsp";
        }
        if (template.contains("form.jsp.vm")) {
            return "main" + File.separator + "pages" + File.separator  +  className.toLowerCase() + File.separator +  className.toLowerCase()+"form.jsp";
        }
        if (template.contains("view.jsp.vm")) {
            return "main" + File.separator + "pages" + File.separator  +  className.toLowerCase() + File.separator +  className.toLowerCase()+"view.jsp";
        }
        return null;
    }
}
